//
//  TXAFHttpManger.m
//  TXKit
//
//  Created by YM on 16/11/24.
//  Copyright © 2016年 Tincent. All rights reserved.
//

#import "TXAFHttpManger.h"
#import "NSObject+TXJSON.h"
#import <AFNetworking.h>
#import <AFNetworkActivityIndicatorManager.h>
#import "TXHttpCache.h"

@interface TXAFHttpManger ()

@end

@implementation TXAFHttpManger

static NSMutableArray *_allSessionTask;
static AFHTTPSessionManager *_sessionManager;

+(id)requestWithUrl:(NSString*) url
            headers:(NSDictionary *)headers
             params:(NSDictionary*) params
             method:(HttpMethod ) method
         cacheBlock:(void (^)(NSDictionary *cacheObj))onCached
        finishBlock:(void (^)(NSDictionary *jsonObj, NSError *error)) onFinished
{
    TXAFHttpManger *reqObj = [[self alloc] initWithParam:YES];
    return [reqObj setRequestUrl:url headers:headers params:params isParamSign:NO method:method cacheBlock:onCached finishBlock:onFinished];
}

+(id)requestWithUrl:(NSString*) url
            headers:(NSDictionary *)headers
             params:(NSDictionary*) params
        isParamSign:(BOOL )isParamSign
     isResponseJson:(BOOL )isResponseJson
             method:(HttpMethod ) method
         cacheBlock:(void (^)(id cacheObj))onCached
        finishBlock:(void (^)(id responseObj, NSError *error)) onFinished
{
    TXAFHttpManger *reqObj = [[self alloc] initWithParam:isResponseJson];
    return [reqObj setRequestUrl:url headers:headers params:params isParamSign:isParamSign method:method cacheBlock:onCached finishBlock:onFinished];
}

/**
 开始监测网络状态
 */
+ (void)load {
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
}

/**
 *  所有的HTTP请求共享一个AFHTTPSessionManager
 */
+ (void)initialize {
    
    _sessionManager = [AFHTTPSessionManager manager];

    //设置服务器接收参数的类型
    _sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];

    //设置请求超时时长
    _sessionManager.requestSerializer.timeoutInterval = 30.f;
    
    // 打开状态栏的等待菊花
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
}

-(id)initWithParam:(BOOL )isResponseJson
{
    self = [super init];
    if (self){
        
        //设置服务器返回结果的类型
        if (isResponseJson) {
            
            _sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];
            _sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/plain", @"text/javascript", @"text/xml", @"image/*", @"audio/*", nil];
        }
        else {
            
            _sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
        }
    }
    return self;
}

-(void )checkIsUserOffline:(NSDictionary *)responseObject error:(NSError *)error {
    
    BOOL hasExistErr = NO;
    
    if (responseObject) {
        
        if ([responseObject isKindOfClass:[NSDictionary class]]) {
            
            NSString *code = [responseObject valueForKey:@"code"];
            
            if (code && ([code integerValue] == TX_HTTP_ERRCODE_UNTOKEN || [code integerValue] == TX_HTTP_ERRCODE_UNLOGIN)) {
                
                hasExistErr = YES;
            }
        }
        
    } else if (error) {
        
        if(error.code == TX_HTTP_ERRCODE_USER_NOT_EXIST || error.code == TX_HTTP_ERRCODE_UNLOGIN) {
            
            hasExistErr = YES;
        }
    }
    
    if(hasExistErr)
    {
        TXLogError(@"用户已下线: %@", _sessionManager.baseURL);
        
        [[NSNotificationCenter defaultCenter] postNotificationName:kNotifyKeyUserOffline object:nil userInfo:nil];
    }
}

-(NSString *)parseErrorMessage:(NSError *)error {
    
    NSDictionary *userinfo1 = [[NSDictionary alloc] initWithDictionary:error.userInfo];
    
    if(userinfo1) {
        
        NSError *innerError = [userinfo1 valueForKey:@"NSUnderlyingError"];
        
        if(innerError) {
            
            NSDictionary *innerUserInfo = [[NSDictionary alloc] initWithDictionary:innerError.userInfo];
            
            if(innerUserInfo) {
                
                NSData *data = [innerUserInfo objectForKey:AFNetworkingOperationFailingURLResponseDataErrorKey];
                
                if(data) {
                    
                    NSString *strError = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                    
                    return strError;
                }
            }
        }
        else {
            
            NSData *data = [userinfo1 valueForKey:@"AFNetworkingOperationFailingURLResponseDataErrorKey"];
            
            if (data) {
                
                NSString *errResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                
                if(errResponse) {
                    
                    return errResponse;
                }
            }
        }
    }
    
    return nil;
}

-(void)printResponseLog:(NSURLSessionDataTask * _Nullable)task responseObject:(id  _Nullable)responseObject error:(NSError *)error {
    
    if (error) {
        
        TXLogError(@"\n【request response!!!!!!!!!!】\n【request url】: \n%@, \n【errorMessage】: \n%@\n", task.currentRequest.URL.absoluteString, [self parseErrorMessage:error]);
    }
    else {
        
        TXLogWarn(@"\n【request response!!!!!!!!!!】\n【request url】: \n%@, \n【responseObject】: \n%@\n", task.currentRequest.URL.absoluteString, [responseObject TXJSONRepresentation]);
    }
}

-(NSURLSessionDataTask *)setRequestUrl:(NSString*) url
                               headers:(NSDictionary*)headers
                                params:(NSDictionary*)params
                           isParamSign:(BOOL )isParamSign
                                method:(HttpMethod ) method
                            cacheBlock:(void (^)(id cacheObj))onCached
                           finishBlock:(void (^)(id responseObj, NSError *error)) onFinished
{
    //header处理
    NSMutableDictionary* allHeaders = [[NSMutableDictionary alloc] initWithCapacity:1];
    {
        //动态header
        [allHeaders addEntriesFromDictionary:headers];
    }

    //参数处理
    NSMutableDictionary* allParams = [[NSMutableDictionary alloc] initWithDictionary:params];
    
    TXLogDebug(@"\n【request begine...】\n【request url】: \n%@, \n【headers】: \n%@\n【params】: \n%@\n", url, allHeaders, allParams);

    NSURLSessionDataTask *task = nil;
    
    TX_THREAD_MAIN(^(void) {
        
        //读缓存
        onCached!=nil ? onCached([TXHttpCache httpCacheForUrl:url parameters:allParams]) : nil;
    });
    
    if (method == HttpGet)
    {
        task = [_sessionManager GET:url parameters:allParams headers:allHeaders progress:^(NSProgress * _Nonnull downloadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            [self printResponseLog:task responseObject:responseObject error:nil];
            
            //写缓存
            onCached!=nil ? [TXHttpCache setHttpCache:responseObject url:url parameters:allParams] : nil;
            
            [self checkIsUserOffline:responseObject error:nil];

            if (onFinished) {
                onFinished(responseObject, nil);
            }
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            [self printResponseLog:task responseObject:nil error:error];
            
            [self checkIsUserOffline:nil error:error];
            
            if (onFinished) {
                onFinished(nil, error);
            }
        }];
    }
    else if (method == HttpPost)
    {
        id file = allParams[@"file"];
        if (file && ([file isKindOfClass:[NSArray class]] || [file isKindOfClass:[UIImage class]] || [file isKindOfClass:[NSData class]])) //上传文件
        {
            task = [_sessionManager POST:url parameters:allParams headers:allHeaders constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
                
                if ([file isKindOfClass:[NSData class]]) { //上传音乐带普通参数
                    NSData *data = (NSData *)file;
                    [formData appendPartWithFileData:data name:@"file" fileName:@"music.caf" mimeType:@"multipart/form-data"];
                } else if ([file isKindOfClass:[NSArray class]]) { //文件数组
                    NSArray *imgFiles = (NSArray *)file;
                    for (int i = 0; i < imgFiles.count; ++i) {
                        UIImage *imgFile = imgFiles[i];
                        NSData *data = UIImagePNGRepresentation(imgFile);
                        [formData appendPartWithFileData:data name:@"file" fileName:@"img.png" mimeType:@"image/png"];
                    }
                } else { //上传图片
                    UIImage *imgFile = (UIImage *)file;
                    NSData *data = UIImagePNGRepresentation(imgFile);
                    [formData appendPartWithFileData:data name:@"file" fileName:@"img.png" mimeType:@"image/png"];
                }
                
            } progress:^(NSProgress * _Nonnull uploadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                [self printResponseLog:task responseObject:responseObject error:nil];
                
                //写缓存
                onCached!=nil ? [TXHttpCache setHttpCache:responseObject url:url parameters:allParams] : nil;
                
                [self checkIsUserOffline:responseObject error:nil];
                
                if (onFinished) {
                    onFinished(responseObject, nil);
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                [self printResponseLog:task responseObject:nil error:error];
                
                [self checkIsUserOffline:nil error:error];
                
                if (onFinished) {
                    onFinished(nil, error);
                }
                
            }];
        }
        else //普通请求
        {
            task = [_sessionManager POST:url parameters:allParams headers:allHeaders progress:^(NSProgress * _Nonnull uploadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                [self printResponseLog:task responseObject:responseObject error:nil];
                
                //写缓存
                onCached!=nil ? [TXHttpCache setHttpCache:responseObject url:url parameters:allParams] : nil;
                
                [self checkIsUserOffline:responseObject error:nil];
                
                if (onFinished) {
                    onFinished(responseObject, nil);
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                [self printResponseLog:task responseObject:nil error:error];
                
                [self checkIsUserOffline:nil error:error];
                
                if (onFinished) {
                    onFinished(nil, error);
                }
                
            }];
        }
    }
    else
    {
        NSAssert(NO, @"the http method %lu is not support now!", (unsigned long)method);
    }
    
    return task;
}

@end
